package gfo

/*Player
* ---------------------------------
* Represents the actual participants who have ever taken part in the tournament series.*/
class Player {
    String fullName
    String description
    int id
    static hasMany = [matches: Matchship]

    static constraints = {
        matches(nullable: true)
        description(nullable: true)
    }

    String toString(){
        "$fullName"
    }

    Fighter strongestFighter(){//copy this into strongestStage & weakest of each
        def fighters = this.charRoster(this.matches.match)
        def ftrRecord = [:]
        for (ftr in fighters){
            if (this.calcWinsByFighter(ftr)[2] > 1){
                ftrRecord[ftr] = this.calcWinsByFighter(ftr)[0] / this.calcWinsByFighter(ftr)[2]
            }
            else{
                ftrRecord[ftr] = 0
            }
        }
        def keys = ftrRecord.keySet().toList()
        def vals = ftrRecord.values().toList()
        return keys[vals.indexOf(vals.max())]
    }

    /*counterPlayerAndFighter
    * ---------------------------------------------
    * Really not sure if this works yet (4/14/13), only have the GFO XIV entered and
    * obviously it wouldn't work for that. pvp seems to be working but my concern is
    * that it doesn't print null for where this data is supposed to be; there's only
    * nothing..enter actual comments later.*/
    Fighter counterPlayerAndFighter(Player opponent, Fighter fighter){//incredibly messy; is there another way?
        def oppMatches = Matchship.findAllByPlayerAndCharacter(opponent, fighter).match
        def record = [:]//1st entry=wins, 2nd=total
        for (match in oppMatches){
            for (ms in match.players){
                if (ms.character && ms.player.id == this.id){
                    if (record.keySet().contains(ms.character)){
                        record[ms.character][1]++
                        if (ms.winner){
                            record[ms.character][0]++
                        }
                    }
                    else{
                        record[ms.character]=[0,1]
                        if (ms.winner){
                            record[ms.character][0]++
                        }
                    }
                }
            }
        }
        if (record.keySet().size()==0 && record.values().size()==0){
            return null
        }
        for (character in record){
            record[character]=record[character][0] / record[character][1]
        }
        def keys = record.keySet().toList()
        def vals = record.values().toList()
        return keys[vals.indexOf(vals.max())]
    }

    List<Fighter> charRoster(List<Match> sMatches){//assumes we've narrowed this down to one player
        def chars = []
        for (match in sMatches){
            for (ms in match.players){
                if (ms.player.id == id){
                    if (!chars.contains(ms.character) && ms.character){
                        chars.add(ms.character)
                    }
                }
            }
        }
        return chars
    }

    List<Fighter> oppCharRoster(List<Match> sMatches){//assumes we've narrowed this down to one player
        def chars = []
        for (match in sMatches){
            for (ms in match.players){
                if (ms.player.id != id){
                    if (!chars.contains(ms.character)){
                        chars.add(ms.character)
                    }
                }
            }
        }
        return chars
    }

    List<Stage> stageRoster(List<Match> sMatches){//assumes we've narrowed this down to one player
        def stages = []
        for (match in sMatches){
            if (!stages.contains(match.stage)){
                stages.add(match.stage)
            }
        }
        return stages
    }

    List<String> showGrid(){
        return ["Wins","Losses","Total"]
    }

    List<Integer> calcWinsByFighter(Fighter character){//may need to take another argument such as stage, etc
        def record = [0, 0, 0]//wins, losses, totals
        for (match in matches){//STRONGLY depends on gsp
            if (match.character && match.character.id == character.id){
                if (match.winner){
                    record[0]++
                }
                else{
                    record[1]++
                }
            }
        }
        record[2]=record[0]+record[1]
        return record
    }

    List<Integer> calcWinsByOppFighter(Fighter character){//may need to take another argument such as stage, etc
        def record = [0, 0, 0]//wins, losses, totals
        for (match in matches.match){//Has to refer to the opposite matchship, so first refers to the common match
            for (ms in match.players){
                if (ms.player.id != this.id && ms.character.id == character.id){
                    if (ms.winner){
                        record[1]++
                    }
                    else{
                        record[0]++
                    }
                }
            }
        }
        record[2]=record[0]+record[1]
        return record
    }

    List<Integer> calcWinsByOppPlayer(Player opponent){//may need to take another argument such as stage, etc
        def record = [0, 0, 0]//wins, losses, totals
        for (match in matches.match){//Has to refer to the opposite matchship, so first refers to the common match
            for (ms in match.players){
                if (ms.player && ms.player.id == opponent.id){
                    if (ms.winner){
                        record[1]++
                    }
                    else{
                        record[0]++
                    }
                }
            }
        }
        record[2]=record[0]+record[1]
        return record
    }

    List<Integer> calcWinsByStage(Stage stage){//may need to take another argument such as stage, etc
        def record = [0, 0, 0]//wins, losses, totals
        for (match in matches){//STRONGLY depends on gsp
            if (match.match.stage.id == stage.id){
                if (match.winner){
                    record[0]++
                }
                else{
                    record[1]++
                }
            }
        }
        record[2]=record[0]+record[1]
        return record
    }

    List<Integer> calcWinsByBracket(Bracket bracket){//may need to take another argument such as stage, etc
        def record = [0, 0, 0]//wins, losses, totals
        for (match in matches){//STRONGLY depends on gsp
            if (match.match.bracket.id == bracket.id){
                if (match.winner){
                    record[0]++
                }
                else{
                    record[1]++
                }
            }
        }
        record[2]=record[0]+record[1]
        return record
    }

    List<Integer> calcWins(){//may need to take another argument such as stage, etc
        def record = [0, 0, 0]//wins, losses, totals
        for (match in matches){//STRONGLY depends on gsp
            if (match.winner){
                record[0]++
            }
            else{
                record[1]++
            }
        }
        record[2]=record[0]+record[1]
        return record
    }
}
